﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using AudioPlayer.Entity;
namespace AudioPlayer.GUI.List {
	/// <summary>
	/// List Collection
	/// </summary>
	internal class ListCollection : BaseEntity,IEnumerable<ListItem> {
		#region Constructor
		public ListCollection() {
			this.First = 0;
			this.Items = new List<ListItem>();
			this.SelectedItems = new List<ListItem>();
		}
		#endregion
		#region Private Voids

		#endregion
		#region Public Voids
		/// <summary>
		/// Adds the specified item.
		/// </summary>
		/// <param name="item">The item.</param>
		public void Add(ListItem item) {
			item.Index = this.Count;
			if (this.Count > 0) {
				this[this.Count - 1].Next = item;
				item.Prev = this[this.Count - 1];
			}
			item.Next = null;
			this.Items.Add(item);
			item.Parent = this;
		}
		public void AddRange(ListItem[] items) {
			for (int i = 0; i < items.Length; i++) {
				Add(items[i]);
			}
		}
		public void AddRange(IList<ListItem> items) {
			for (int i = 0; i < items.Count; i++) {
				Add(items[i]);
			}
		}
		public void Rebound() {
			if (this.HasItems) {
				int y = 20;

				for (int i = this.First; i < (this.First + this.Visible); i++) {
					if (i < this.Count) {
						this[i].Bounds = new Rectangle(0, y, this.Width, 20);
						y += 20;
					}
				}

			}
		}

		public void Clear() {
			this.Items.Clear();
			this.SelectedItems.Clear();
			this.First = 0;
		}

		public void ScrollUp() {
			this.ScrollUp(1);
		}
		public void ScrollDown() {
			this.ScrollDown(1);
		}
		public void ScrollUp(int step) {
			if (this.CanScrollUp) {
				int first = this.First;
				if ((this.First - step) > 0) {
					this.First -= step;
				} else {
					this.First = 0;
				}
				this.SetVisibility(true, this.First, this.End);
				this.SetVisibility(false, this.End, this.End + step);
				this.Rebound();
			}
		}
		public void ScrollDown(int step) {
			if (this.CanScrollDown) {
				if ((this.First + this.Visible + step) < this.Count) {
					this.First += step;
				} else {
					if ((this.Count - this.Visible) > 0) {
						this.First = this.Count - this.Visible;//End
					}
				}
				this.SetVisibility(false, this.First - step, this.First);
				this.SetVisibility(true, this.First, this.End);
				this.Rebound();
			}
		}

		public ListItem HitInfo(Point p) {
			for (int i = this.First; i < this.End; i++) {
				if (i < this.Count) {
					ListItem item = this[i];
					if (item.Bounds.Contains(p)) {
						return item;
					}
				}
			}
			return null;
		}
		public ListItem HitHover(Point p) {
			for (int i = this.First; i < this.End; i++) {
				if (i < this.Count) {
					ListItem item = this[i];
					if (item.Bounds.Contains(p)) {
						return item;
					}
				}
			}
			return null;
		}
		public void SetVisibility(bool visible) {
			for (int i = 0; i < this.Count; i++) {
				this[i].Visible = visible;
			}
		}
		public void SetVisibility(bool visible, int start) {
			if (start < this.Count) {
				for (int i = start; i < this.Count; i++) {
					this[i].Visible = visible;
				}
			}
		}
		public void SetVisibility(bool visible, int start, int end) {
			for (int i = start; i < end; i++) {
				if (this.Count > i) {
					this[i].Visible = visible;
				} else {
					break;
				}
			}
		}
		public void SetSlideDefault(IList<ListItem> list) {
			for (int i = 0; i < list.Count; i++) {
				ListItem item = list[i];
				if (item.Index > 0 && (item.Index + 1) < this.Count) {
					//Middle;
					item.Next = this[item.Index + 1];
					item.Prev = this[item.Index - 1];
					item.Selected = true;
				} else {
					if (item.Index == 0) {
						//Top
						item.Next = this[item.Index + 1];
					} else {
						//Bottom
						item.Prev = this[item.Index - 1];
					}
				}
			}
		}
		public void SetSlideSelect(IList<ListItem> list) {
			for (int i = 0; i < list.Count; i++) {
				if (i > 0 && (i + 1) < list.Count) {
					//Middle
					list[i].Next = list[i + 1];
					list[i].Prev = list[i - 1];
				} else {
					if (i == 0) {
						//Top
						if (list.Count > 1) {
							list[i].Next = list[i + 1];
							list[i].Prev = null;
						}
					} else {
						//Bottom
						if (list.Count > 1) {
							list[i].Prev = list[i-1];
							list[i].Next = null;
						}
					}
				}
			}
		}
		/// <summary>
		/// Gets the neighbours.
		/// </summary>
		/// <param name="index">Index.</param>
		/// <returns>List of neighbours</returns>
		public IList<ListItem> GetNeighbours(int index) {
			List<ListItem> list = new List<ListItem>();
			if (index > 0 && this.Count > index) {
				ListItem item = this[index];

				//Add previous items
				if (item.Prev != null) {
					list.Add(item.Prev);
				}
				//Add self
				list.Add(item);
				//And and next items
				if (item.Next != null) {
					list.Add(item.Next);
				}
			}
			return list;
		}
		/// <summary>
		/// Gets the neighbours.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <returns></returns>
		public IList<ListItem> GetNeighbours(ListItem item) {
			IList<ListItem> list = new List<ListItem>();
			if (item.Prev != null) {
				list.Add(item.Prev);
			}
			list.Add(item);
			if (item.Next != null) {
				list.Add(item.Next);
			}
			return list;
		}

		/// <summary>
		/// Selects all items.
		/// </summary>
		public void SelectAll() {
			throw new NotImplementedException();
		}
		/// <summary>
		/// Unselects all items
		/// </summary>
		public void SelectNone(){
			if (this.SelectedItems != null) {
				for (int i = 0; i < this.SelectedItems.Count; i++) {
					this.SelectedItems[i].Selected = false;
				}
			}
			//this.SelectedItems.Clear();
		}
		#endregion
		#region Override
		public override string ToString() {
			return (String.Format("Count:{0}", this.Count));
		}
		#endregion
		#region Property
		public ListItem SelectedFirst {
			get {
				if (this.SelectedItems != null) {
					if (this.SelectedItems.Count > 0) {
						return this.SelectedItems[0];
					}
				}
				return null;
			}
			set {
				if (this.SelectedItems != null) {
					this.SelectedItems.Clear();
					this.SelectedItems.Add(value);
				} else {
					this.SelectedItems = new List<ListItem>();
					this.SelectedItems.Add(value);
				}
			}
		}
		public IList<ListItem> SelectedItems {
			get {
				return this.GetValue<IList<ListItem>>("SelectedItems");
			}
			set {
				this.SetValue<IList<ListItem>>("SelectedItems", value);
			}
		}
		public int SelectedCount {
			get {
				if (this.SelectedItems != null) {
					return this.SelectedItems.Count;
				}
				return 0;
			}
		}
		public ListItem Hover {
			get { return this.GetValue<ListItem>("Hover"); }
			set { this.SetValue<ListItem>("Hover",value); }
		}
		public ListItem this[int index] {
			get { return this.Items[index]; }
			set { this.Items[index] = value; }
		}
		protected List<ListItem> Items {
			get { return this.GetValue<List<ListItem>>("Items"); }
			set { this.SetValue<List<ListItem>>("Items", value); }
		}
		public int First {
			get { return this.GetValue<int>("First"); }
			set {this.SetValue<int>("First",value); }
		}
		public int End {
			get { return (this.First + this.Visible); }
		}
		public int Visible {
			get { return this.GetValue<int>("Visible"); }
		}
		public int Height {
			get {
				return this.GetValue<int>("Height");
			}
			set {
				if (value > 0) {
					this.SetValue<int>("Visible",((value - 20) / 20));
					this.SetValue<int>("Height",value);
				}
			}
		}
		public int Width {
			get { return this.GetValue<int>("Width"); }
			set { this.SetValue<int>("Width",value); }
		}
		public bool HasItems {
			get {
				if (this.Count > 0) {
					return true;
				} else {
					return false;
				}
			}
		}
		public bool CanScrollUp {
			get {
				if (this.First > 0) {
					return true;
				} else {
					return false;
				}
			}
		}
		public bool CanScrollDown {
			get {
				if ((this.First + this.Visible) < this.Count) {
					return true;
				} else {
					return false;
				}
			}
		}
		public new int Count {
			get { return this.Items.Count; }
		}
		#endregion

		#region Enumerator

		public IEnumerator<ListItem> GetEnumerator() {
			return this.Items.GetEnumerator();
		}
		IEnumerator IEnumerable.GetEnumerator() {
			return this.Items.GetEnumerator();
		}

		#endregion
	}
}
